// 组件 provide 和 inject 功能  （父组件通过provide提供的数据，可以让任意子孙组件通过inject获取） - 用原型链实现而不是用循环递归查找
import { h, provide, inject, } from '../../lib/guide-mini-vue.esm.js';

/**提供数据组件 - 1号 - 根组件 - 第一子组件是ProviderTwo */
const ProviderOne = {
  setup() {
    const _foo = "foo爷爷"
    const _bar = "bar"
    provide("foo", _foo);
    provide("bar", _bar);
    return { _foo, _bar }
  },
  render() {
    const { _foo, _bar } = this
    return h('div', {}, [
      h('p', { style: 'color: red' }, `这里是爷爷组件，提供了数据 foo: ${_foo} , bar: ${_bar}`),
      h(ProviderTwo)
    ])
  }
};
/**提供数据组件 - 2号 - 二层组件 - 子组件是Consumer，父组件是ProviderOne */
const ProviderTwo = {
  setup() {
    const _foo = "foo爸爸"
    const _baz = "baz"
    provide("foo", _foo);
    provide("baz", _baz);
    const foo = inject("foo");
    // 这里获取的 foo 的值应该是 "foo"
    // 这个组件的子组件获取的 foo ，才应该是 fooOverride
    if (foo !== "foo爷爷") {
      console.warn(`父亲组件，这里获取的 foo 的值应该是 'foo爷爷'，这个组件的子组件（孙子组件）获取的 foo ，才应该是 ${_foo}`,
        "也就是说，如果同时存在多个相同键值，取 离自己组件最近的那个"
      );
    }
    return { foo, _foo, _baz }
  },
  render() {
    const { foo, _foo, _baz } = this
    return h('div', {}, [
      h('p', { style: 'color: blue' }, `这里是父亲组件，提供了数据 foo: ${_foo} , baz: ${_baz}， 接收到上层数据：foo: ${foo}`),
      h(Consumer)
    ])
  }
};
/**使用者组件 - 底层组件 - 父组件是ProviderTwo */
const Consumer = {
  setup() {
    const foo = inject("foo");
    const bar = inject("bar");
    const baz = inject("baz");
    const not = inject("not", "父组件没给这个，就使用默认值");//父组件没给这个，就使用默认值
    const fn = inject("fn", () => "还可以传递函数，这是函数返回值");//还可以传递函数，这是函数返回值
    return { foo, bar, baz, not, fn }
  },
  render() {
    const { foo, bar, baz, not, fn } = this
    return h("div", {}, `这里是孙子组件：拿到数据：\n
     foo是${foo} 、\n
     bar是${bar} 、\n
     baz是${baz} 、\n
     父组件没有的话使用默认值：${not} 、\n
     还可以用函数： ${fn} \n
      `);
  }
};

export default {
  name: "App",
  setup() {

  },
  render() {
    return h("div", {}, [h("p", {}, "apiInject"), h(ProviderOne)]);
  }
};
